/**
 * 
 * @param {Object} options 发送请求参数
 */
function ajax(options){
    //设置默认信息
    let defaults={
        method:'get',//请求方式
        url:'', //请求地址
        data:'', //请求参数
        contentType:'application/x-www-form-urlencoded', //表示设置请求头Content-Type  ,对应的值
        dataType:'json' ,//表示服务端默认返回的数据格式
        callback:function(){}, //表示拿到服务端结果之后的处理方式，是哟个回调函数
    }
    //传参之后需要覆盖默认值
    for(let key in defaults){
        options[key] && (defaults[key]=options[key]);
    }
    //检查每一个参数是否满足要求
    /* 检查url地址是否传递 */
    if(!defaults.url){
        throw new Error('url地址必须传递');
    }
    /* 检查请求方式是否传递 */
    let methodType=['get','post','put','delete'];
    defaults.method=defaults.method.toLocaleLowerCase();
    if(!methodType.includes(defaults.method)){
        throw new Error('请求方式设置错误');
    }
    /*请求参数数据格式是否正确，两种情况，可能是对象，也可能是字符串*/
    let dataClass=Object.prototype.toString.call(defaults.data);
    if(dataClass!='[object String]'&& dataClass!='[object Object]'){
        throw new Error('请求参数格式格式错误');
    }   
    /* 验证回调，要求必须是函数 */
    if(Object.prototype.toString.call(defaults.callback)!='[object Function]'){
        throw new Error('回调必须是一个函数');
    }
    // 构建请求携带的数据，无论是什么情况，转成字符串即可
    let data='';
    if(Object.prototype.toString.call(defaults.data)=='[object string]'){
        data=defaults.data;
    }else{
        //如果是get,delete请求 字符串最终需要放到URL地址上 格式key/value格式，如果是post，put请求 格式 有可能是key/value格式 也可能是JSON格式
        if((defaults.method=='post'||defaults.method=='put')&&defaults.contentType=='application/json'){
            //设置请求参数为JSON格式 
            data=JSON.stringify(defaults.data);
        }else{
            for (let key in defaults.data){
                data+=`${key}=${defaults.data[key]}&`
            }
            data=data.substr(0,data.length-1);
        }
    }
    //获取Ajax对象
    let xhr=new XMLHttpRequest;
    //打开连接
    let url=defaults.url
    if((defaults.method=='get'||defaults.method=='delete')&&data){
        url=defaults.url+'?'+data;
    }
    xhr.open(defaults.method,url);
    //发送请求  判断请求方式为post或者put  并且data中有参数需要携带  所以才使用data  否则就传递空

    xhr.send(((defaults.method=='post'||defaults.method=='put')&&data)?date:'');
    //监听状态改变
    xhr.onreadystatechange=function(){
        if(xhr.status==200&&xhr.readyState==4){
            let response=(defaults.dataType=='json')?JSON.parse(xhr.responseText):xhr.responseText;
            defaults.callback(response);

        }
    }
}
